package hkust.ee.fyp;

import hkust.ee.fyp.tool.Directory;
import hkust.ee.fyp.tool.FacebookPhoto;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.util.List;
import java.util.Vector;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.AdapterView.OnItemClickListener;

import com.facebook.android.DialogError;
import com.facebook.android.Facebook;
import com.facebook.android.FacebookError;
import com.facebook.android.Facebook.DialogListener;

public class PhotoFrame extends Activity {

	public static final String TAG = "PHOTO_FRAME";
	public static final String rootDir = "/sdcard";
//	public static final String rootDir = "/sdcard/Pictures";
	private boolean isFolderView = true;
	private Vector<Directory> imageDirectory = null;
	private Directory directory = null;
	private ProgressDialog progressDialog = null;	
	
//	menu
//	protected static final int MENU_REFRESH = Menu.FIRST;
	protected static final int MENU_SETTING = Menu.FIRST ;
	protected static final int MENU_FB = Menu.FIRST + 1;
	protected static final int MENU_SLIDESHOW = Menu.FIRST + 2;
	
//	handler
	private Handler uiHandler,dataHandler;
	public static final int HANDLER_REFRESH = 0;
	public static final int HANDLER_THUMBNAIL = 1;
	public static final int HANDLER_FACEBOOK_TOKEN = 2;
	public static final int HANDLER_PROGRESSDIALOG_SHOW = 3;
	public static final int HANDLER_PROGRESSDIALOG_DISMISS = 4;
	public static final int HANDLER_TOFOLDER = 5;
	public static final int HANDLER_TOIMAGE = 6;
	//facebook
	private static final String APP_ID = "207571395929037";
	private static final String[] PERMISSIONS = new String[] { "user_photos",
			"friends_photos", "user_status", "email", "read_friendlists",
			"read_stream", "publish_stream " };
	Facebook facebook = new Facebook(APP_ID);
	
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		SharedPreferences settings = getSharedPreferences(TAG, 0);
		facebook.setAccessToken(settings.getString("facebookToken", null));

//		requestWindowFeature(Window.FEATURE_NO_TITLE);
// 		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

		uiHandler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
					case HANDLER_FACEBOOK_TOKEN:{
						SharedPreferences settings = getSharedPreferences(TAG, 0);
					    SharedPreferences.Editor editor = settings.edit();
					    editor.putString("facebookToken", (String) msg.obj);
					    editor.commit();
					    break;
					}
					case HANDLER_PROGRESSDIALOG_SHOW:{
						if(progressDialog !=null && progressDialog.isShowing()){
	
						}else{
							progressDialog = ProgressDialog.show(PhotoFrame.this, "","Loading...", false, false);
//							Log.d("handler", "show");
						}
						break;
					}
					case HANDLER_PROGRESSDIALOG_DISMISS:{
						if(progressDialog!=null){
							progressDialog.dismiss();
						}
						break;
					}
					case HANDLER_TOFOLDER:{
						toFolderPage();
						break;
					}
					case HANDLER_TOIMAGE:{
						
						if(msg.obj !=null){
							toImagePage((Directory) msg.obj);
						}else{
							Directory dir=null;
							for(Directory d: imageDirectory){
								if(d.getCurrentPath().getAbsolutePath().compareTo(directory.getCurrentPath().getAbsolutePath()) ==0){
									dir = d;
									break;
								}
							}
							if(dir!=null){
								toImagePage(dir);
							}else{
								toFolderPage();
							}
						}
						
						break;
					}
				}
			}
		};
		
		new Thread(){
			public void run(){
				Log.d("looper", "run start");
				Looper.prepare();
				dataHandler = new Handler() {
					public void handleMessage(Message msg) {				
						switch (msg.what) {							
							case HANDLER_REFRESH:
								uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_SHOW);
								refreshSDcard(false);
								uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_DISMISS);
								if(isFolderView){
									uiHandler.sendEmptyMessage(HANDLER_TOFOLDER);
								}else{
									uiHandler.sendEmptyMessage(HANDLER_TOIMAGE);
								}
								
								break;
							
							case HANDLER_THUMBNAIL:
								uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_SHOW);
								Directory dir = (Directory) msg.obj;
								int size = dir.getImageList().size();
								String thumbPath = dir.getCurrentPath() + "/.thumbnails/";
								for (int i=0;i<size;i++) {;
									Uri imageUri = dir.getImageList().get(i);
									String name = dir.getImageNameList().get(i);
//									Log.d(TAG, imageUri.getPath());
									Bitmap destBm=null;
									try {
//										Log.d(TAG, thumbPath+name);
										File f =  new File(thumbPath+name);
										if(!f.exists()){
											f.createNewFile();
											
											int maxLength = 200;	  
									        BitmapFactory.Options opts = new BitmapFactory.Options();  	
									        opts.inJustDecodeBounds = true;
									        BitmapFactory.decodeFile(imageUri.getPath(), opts);  
									  
									        int srcWidth = opts.outWidth;  		  
									        int srcHeight = opts.outHeight;  
									  
									        int destWidth = 0;  		  
									        int destHeight = 0;  
									  
									        double ratio = 0.0;
									  
									       if(srcWidth >srcHeight) {
										        ratio = srcWidth / maxLength;  
										        destWidth = maxLength;  
										        destHeight = (int) (srcHeight / ratio);
									        }else {  
									            ratio = srcHeight / maxLength;
									            destHeight = maxLength;  
									            destWidth = (int) (srcWidth / ratio);
									        }  
									  
									        BitmapFactory.Options newOpts = new BitmapFactory.Options();  
									        newOpts.inSampleSize = (int) ratio + 1;  
									        newOpts.inJustDecodeBounds = false;  
									        newOpts.outHeight = destHeight;
									        newOpts.outWidth = destWidth;  
											
									        destBm = BitmapFactory.decodeFile(imageUri.getPath(), newOpts); 	
											FileOutputStream out = new FileOutputStream(thumbPath+name);
											destBm.compress(Bitmap.CompressFormat.PNG, 100, out);
											out.flush();
											out.close();
										}
									} catch (Exception e) {
										e.printStackTrace();
									} finally{
										if (null != destBm && !destBm.isRecycled()) {
											destBm.recycle();
										}
									}
								}
								uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_DISMISS);
								Message m = Message.obtain();
								m.obj = dir; 
								m.what = HANDLER_TOIMAGE;
								uiHandler.sendMessage(m);
								break;
						
						}
					}
				};
				Looper.loop();
				Log.d("looper", "run end");
			}
		}.start();
		
		while(dataHandler==null){
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}	
	
	protected void onResume() {
		super.onResume();
		dataHandler.sendEmptyMessage(HANDLER_REFRESH);		
	}
	
	
	private void refreshSDcard(boolean deleteThumb) {
		uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_SHOW);
		imageDirectory = new Vector<Directory>();		
		Directory.recursiveSearchDir(imageDirectory, new File(rootDir));
		for (Directory d : imageDirectory) {
//			Log.d(TAG, d.getCurrentName());
			String thumbPath = d.getCurrentPath() + "/.thumbnails/";
//			Log.d(TAG, thumbPath);
			File file = new File(thumbPath);
			if(deleteThumb){
				if (file.exists()) {
					try {
						Directory.deleteRecursive(file);
					} catch (FileNotFoundException e) {
						e.printStackTrace();
					}
				}
			}
			file.mkdir();
			
//			create first photo thumbnail
//			int size = d.getImageList().size();
			int size = 1;
			for (int i=0;i<size;i++) {;
				Uri imageUri = d.getImageList().get(i);
				String name = d.getImageNameList().get(i);
//				Log.d(TAG, imageUri.getPath());
				Bitmap destBm=null;
				try {
//					Log.d(TAG, thumbPath+name);
					File f =  new File(thumbPath+name);
					if(!f.exists()){
						f.createNewFile();
						
						int maxLength = 200;	  
				        BitmapFactory.Options opts = new BitmapFactory.Options();  	
				        opts.inJustDecodeBounds = true;
				        BitmapFactory.decodeFile(imageUri.getPath(), opts);  
				  
				        int srcWidth = opts.outWidth;  		  
				        int srcHeight = opts.outHeight;  
				  
				        int destWidth = 0;  		  
				        int destHeight = 0;  
				  
				        double ratio = 0.0;
				  
				       if(srcWidth >srcHeight) {
					        ratio = srcWidth / maxLength;  
					        destWidth = maxLength;  
					        destHeight = (int) (srcHeight / ratio);
				        }else {  
				            ratio = srcHeight / maxLength;
				            destHeight = maxLength;  
				            destWidth = (int) (srcWidth / ratio);
				        }  
				  
				        BitmapFactory.Options newOpts = new BitmapFactory.Options();  
				        newOpts.inSampleSize = (int) ratio + 1;  
				        newOpts.inJustDecodeBounds = false;  
				        newOpts.outHeight = destHeight;
				        newOpts.outWidth = destWidth;  
						
				        destBm = BitmapFactory.decodeFile(imageUri.getPath(), newOpts); 	
						FileOutputStream out = new FileOutputStream(thumbPath+name);
						destBm.compress(Bitmap.CompressFormat.PNG, 100, out);
						out.flush();
						out.close();
					}
				} catch (Exception e) {
					e.printStackTrace();
				} finally{
					if (null != destBm && !destBm.isRecycled()) {
						destBm.recycle();
					}					
				}
			}
		}

		uiHandler.sendEmptyMessage(HANDLER_PROGRESSDIALOG_DISMISS);
	}

	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
//		menu.add(0, MENU_REFRESH, 0, "refresh sd card");
		menu.add(0, MENU_SETTING, 0, "facebook login");
		menu.add(0, MENU_FB, 0, "Facebook Photo");
		menu.add(0, MENU_SLIDESHOW, 0, "Slideshow");
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		super.onOptionsItemSelected(item);
		switch (item.getItemId()) {
//			case MENU_REFRESH:
//				dataHandler.sendEmptyMessage(HANDLER_REFRESH);		
//				break;
			case MENU_SETTING:
				if(facebook.isSessionValid()){
					facebookLogout();
				}else{
					facebookLogin();
				}
				break;
			case MENU_FB:
				if(facebook.isSessionValid()){
					Intent i = new Intent(this,FacebookActivity.class);
					startActivity(i);
				}else{
					Toast.makeText(PhotoFrame.this, "Please login first", Toast.LENGTH_SHORT);
				}
//				downloadFBPhoto();				
				break;
			case MENU_SLIDESHOW:
				if(isFolderView){
					Toast.makeText(this, "This is not a folder",Toast.LENGTH_SHORT).show();
				}else{
					Intent i = new Intent(this, PhotoViewer.class);
					i.putExtra("slideshow", true);
					i.putExtra("directory", directory.getCurrentPath().toString());
					startActivity(i);
				}
				break;
		}
		return true;
	}
	
	private void toFolderPage() {
		if(imageDirectory==null){
			dataHandler.sendEmptyMessage(HANDLER_REFRESH);
			return;
		}
//		for(int i=0;i<dir.size();i++){
//			Log.d("toFolderPage", dir.get(i).getCurrentName() + dir.get(i).getImageList().size());
//			for(int j=0;j<dir.get(j).getImageList().size();j++){
//				Log.d("toFolderPage", dir.get(i).getImageList().get(j) + " " +j);
//			}
//		}
		
		isFolderView = true;
		directory = null;
		
		View view = getLayoutInflater().inflate(R.layout.gallery_gridlayout_folder,null);
		GridView gridview = (GridView) view.findViewById(R.id.folder_gridView);
		FolderAdapter adapter = new FolderAdapter( imageDirectory);
		gridview.setAdapter(adapter);
		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,int position, long id) {
				Message msg = Message.obtain();
				msg.obj = imageDirectory.get(position);
				msg.what = HANDLER_THUMBNAIL;
				dataHandler.sendMessage(msg);
			}
		});

		setContentView(view);
	}


	private void toImagePage(final Directory dir) {
		isFolderView = false;
		directory = dir;
		
		View view = getLayoutInflater().inflate(R.layout.gallery_gridlayout_image,null);
		GridView gridview = (GridView) view.findViewById(R.id.image_gridView);
		
		ImageAdapter adapter = new ImageAdapter( dir.getThumbnaiList());
		gridview.setAdapter(adapter);
		gridview.setOnItemClickListener(new OnItemClickListener() {
			public void onItemClick(AdapterView<?> parent, View v,int position, long id) {
				openImage(dir.getImageList().get(position));
			}
		});

		setContentView(view);
	}

	private void openImage(Uri path) {
		Intent i = new Intent(this, PhotoViewer.class);
		i.setDataAndType(Uri.parse("file://" + path), "image/*");
		startActivity(i);
	}

	private void downloadFBPhoto(){
		File file = new File(rootDir + "/fbPhoto/");
		try {
			Directory.deleteRecursive(file);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		file.mkdir();
		new Thread(){
			public void run(){
				final List<FacebookPhoto> photoList = facebookDownloadAlbum(rootDir+"/fbPhoto/");
				NotificationManager mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
				Notification notification = new Notification(R.drawable.icon,"PhotoFrame", System.currentTimeMillis());
				notification.setLatestEventInfo(PhotoFrame.this,"Facebook download", "start...",
				PendingIntent.getActivity(PhotoFrame.this, 0, null,	PendingIntent.FLAG_ONE_SHOT));
			    mManager.notify(0, notification);
				if(photoList != null){
					Thread t = new Thread(){
						public void run(){
							for(FacebookPhoto single : photoList){
								single.start();
								try {
									single.join();
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
							}				
							NotificationManager mManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
							Notification notification = new Notification(R.drawable.icon,"PhotoFrame", System.currentTimeMillis());
							notification.setLatestEventInfo(PhotoFrame.this,"Facebook download", "finish...",
							PendingIntent.getActivity(PhotoFrame.this, 0, null,	PendingIntent.FLAG_ONE_SHOT));
						    mManager.notify(0, notification);
						}
					};
					t.start();
				}
			}
		}.start();
		
	}
	
	public boolean onKeyDown(int keyCode, KeyEvent msg) {
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (!isFolderView) {
				toFolderPage();
				return true;
			}
		}

		return super.onKeyDown(keyCode, msg);
	}

	

	public class ImageAdapter extends BaseAdapter {
		private List<Uri> list = null;

		public ImageAdapter( List<Uri> list) {
			this.list = list;
		}

		public int getCount() {
			return list.size();
		}

		public Object getItem(int position) {
			return null;
		}

		public long getItemId(int position) {
			return 0;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) { 
				view = PhotoFrame.this.getLayoutInflater().inflate(R.layout.image_adapter, null);				
			} else {
				view = convertView;
			}
			
			((ImageView) view.findViewById(R.id.image_adapter_imageView))
				.setImageURI(list.get(position));
			
			return view;
		}
	}
	
	public class FolderAdapter extends BaseAdapter {
		private List<Directory> list = null;

		public FolderAdapter(List<Directory> list) {
			this.list = list;			
		}

		public int getCount() {
			return list.size();
		}

		public Object getItem(int position) {
			return null;
		}

		public long getItemId(int position) {
			return 0;
		}

		
		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) { 
				view = PhotoFrame.this.getLayoutInflater().inflate(R.layout.folder_adapter, null);				
			} else {
				view = convertView;				
			}
			((ImageView) view.findViewById(R.id.folder_adapter_imageView))
				.setImageURI(list.get(position).getThumbnaiList().get(0));
			((TextView) view.findViewById(R.id.folder_adapter_textView))
				.setText(list.get(position).getCurrentName());
						
			return view;
		}
	}
	
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
	    facebook.authorizeCallback(requestCode, resultCode, data);
		super.onActivityResult(requestCode, resultCode, data);
	}

	
	public void facebookLogin(){
	    facebook.authorize(this, PERMISSIONS,new DialogListener() {
	    	
			public void onComplete(Bundle values) {
				Log.d("FB Sample App", "LoginDialogListener.onComplete()");
				Toast.makeText(PhotoFrame.this, "Login Success", Toast.LENGTH_SHORT).show();
				Message msg =Message.obtain();
				msg.what = HANDLER_FACEBOOK_TOKEN;
				msg.obj = facebook.getAccessToken();
				uiHandler.sendMessage(msg);					
			}

			public void onFacebookError(FacebookError error) {
				Log.d("FB Sample App", "LoginDialogListener.onFacebookError()");
				Toast.makeText(PhotoFrame.this, "Login fail", Toast.LENGTH_SHORT).show();
			}

			public void onError(DialogError error) {
				Log.d("FB Sample App", "LoginDialogListener.onError()");
				Toast.makeText(PhotoFrame.this, "Login fail", Toast.LENGTH_SHORT).show();
			}

			public void onCancel() {
				Log.d("FB Sample App", "LoginDialogListener.onCancel()");

			}
		} );
	}
	
	public void facebookLogout(){
		try {
			facebook.logout(this);
			Toast.makeText(this, "Logout Success", Toast.LENGTH_SHORT).show();
			Message msg = Message.obtain();
			msg.what = PhotoFrame.HANDLER_FACEBOOK_TOKEN;
			msg.obj = null;
			uiHandler.sendMessage(msg);
		} catch (Exception e) {
			e.printStackTrace();
			Toast.makeText(this, "Logout fail", Toast.LENGTH_SHORT).show();
		}		
		
	}
	
	
	public List<FacebookPhoto> facebookDownloadAlbum(String pathName) {
		if (!facebook.isSessionValid()) {
			Toast.makeText(this, "Please login first", Toast.LENGTH_SHORT).show();
			return null;
		}
		
		List<String> albumID = new Vector<String>();
		List<String> albumName = new Vector<String>();
		List<FacebookPhoto> photoList = new Vector<FacebookPhoto>();
		try {
			String response = facebook.request("me/albums");
			Log.d(TAG, response);
			try {
				JSONObject json = new JSONObject(response);
				JSONArray d = json.getJSONArray("data");
				int l = (d != null ? d.length() : 0);

				for (int i = 0; i < l; i++) {
					JSONObject o = d.getJSONObject(i);
					albumName.add(o.getString("name"));
					albumID.add(o.getString("id"));

				}
				
				int size = albumName.size();
				for (int j = 0; j < size; j++) {
					String albumPath = pathName + albumName.get(j) + "/";
					String aid = albumID.get(j);
					File file = new File(albumPath);
					file.mkdir();
					
					response = facebook.request(aid + "/photos");
					Log.d(TAG, response);
					json = new JSONObject(response);
					d = json.getJSONArray("data");
					l = (d != null ? d.length(): 0);

					for (int i = 0; i < l; i++) {
						JSONObject o = d.getJSONObject(i);
						FacebookPhoto photo =
							new FacebookPhoto(albumPath,o.getString("id")
								,o.getString("source"),o.getJSONArray("images").get(1).toString());
						photoList.add(photo);
					}						
				}
				
				Log.d(TAG, "ALL");
			} catch (JSONException e) {
				Log.w("Facebook-Example", "JSON Error in response");
			}
			
		} catch (MalformedURLException e1) {
			e1.printStackTrace();
		} catch (IOException e1) {
			e1.printStackTrace();
		}
		
		return photoList;
	}
}